#include <mutex>

#include "common/elements/element.h"
#include "common/more/string.h"

#include "item_field.h"

namespace Elements
{

ItemField::ItemField(const ItemField& other)
    : Element(other)
    , m_itemId(other.m_itemId)
    , m_fieldTypeId(other.m_fieldTypeId)
    , m_value(other.m_value)
    , m_searchValue(other.m_searchValue)
{
}

bool ItemField::isSame(Element* const other) const
{
    const auto otherElement = dynamic_cast<ItemField const*>(other);
    if (nullptr == otherElement)
        return false;

    return bool(
        m_id == otherElement->m_id
        && m_itemId == otherElement->m_itemId
        && m_fieldTypeId == otherElement->m_fieldTypeId
        && m_value == otherElement->m_value
        && m_searchValue == otherElement->m_searchValue
    );
}

Common::Json ItemField::toJson() const
{
    std::shared_lock locker(m_lock);
    Common::Json result;
    result["id"] = m_id;
    result["elementType"] = unsigned(elementType());
    result["itemId"] = m_itemId;
    result["fieldTypeId"] = m_fieldTypeId;
    result["value"] = m_value;
    result["searchValue"] = m_searchValue;
    return result;
}

void ItemField::fromJson(const Common::Json& json)
{
    std::shared_lock locker(m_lock);
    m_id = json["id"].get<unsigned>();
    m_itemId = json["itemId"].get<unsigned>();
    m_fieldTypeId = json["fieldTypeId"].get<unsigned>();
    m_value = json["value"].get<std::string>();
    m_searchValue = json["searchValue"].get<std::string>();
}

Element* ItemField::clone() const
{
    return new ItemField(*this);
}

ElementType ItemField::elementType() const
{
    return ElementType::ItemField;
}

unsigned ItemField::itemId() const
{
    std::shared_lock locker(m_lock);
    return m_itemId;
}

void ItemField::setItemId(unsigned value)
{
    std::unique_lock locker(m_lock);
    m_itemId = value;
}

unsigned ItemField::fieldTypeId() const
{
    std::shared_lock locker(m_lock);
    return m_fieldTypeId;
}

void ItemField::setFieldTypeId(unsigned value)
{
    std::unique_lock locker(m_lock);
    m_fieldTypeId = value;
}

std::string ItemField::value() const
{
    std::shared_lock locker(m_lock);
    return m_value;
}

void ItemField::setValue(const std::string& value)
{
    std::unique_lock locker(m_lock);
    m_value = value;
    locker.unlock();
    setSearchValue(value);
}

std::string ItemField::searchValue() const
{
    std::shared_lock locker(m_lock);
    return m_searchValue;
}

void ItemField::setSearchValue(const std::string& value)
{
    std::unique_lock locker(m_lock);
    m_searchValue = Common::toLowerCase(value);
}

} // namespace Elements
